// SPDX-License-Identifier: GPL-2.0-only
/*
 * Example code for CSV RTMR & ATTESTATION.
 *
 * Copyright (C) 2025 Hygon Info Technologies Ltd.
 *
 * Author: Liyang Han <hanliyang@hygon.cn>
 */

#ifndef __CSV_RTMR_H__
#define __CSV_RTMR_H__

#include <linux/types.h>
#include <linux/ioctl.h>

int handle_subcmd_rtmr(int argc, char *argv[]);


/* The CSV RTMR version in the kernel */
#define CSV_RTMR_VERSION_MAX	1U
#define CSV_RTMR_VERSION_MIN	1U

/* The size of CSV RTMR register. */
#define CSV_RTMR_REG_SIZE	32 /* SM3 */

/* The size of the CSV RTMR extend data. */
#define CSV_RTMR_EXTEND_LEN	CSV_RTMR_REG_SIZE

/*
 * The number of the CSV RTMR registers.
 *
 * For version 1, the number of RTMR registers for a guest is 5. The mapping
 * from TPM2 PCR index to RTMR index is shown as follows:
 *
 *   +---------------+--------------------------------------+---------+
 *   | TPM PCR Index | Event Log Measurement Register Index |  RTMR   |
 *   |---------------|--------------------------------------|-------- |
 *   |    0          |    0                                 | RTMR[0] |
 *   |    1,7        |    1                                 | RTMR[1] |
 *   |    2~6        |    2                                 | RTMR[2] |
 *   |    8~15       |    3                                 | RTMR[3] |
 *   |    16,23      |    4                                 | RTMR[4] |
 *   +---------------+--------------------------------------+---------+
 */
#define CSV_RTMR_REG_NUM	5

/* The maximum index of the CSV RTMR registers. */
#define CSV_RTMR_REG_INDEX_MAX	(CSV_RTMR_REG_NUM - 1)

enum csv_guest_user_rtmr_subcmd {
	CSV_GUEST_USER_RTMR_STATUS	= 0x1,
	CSV_GUEST_USER_RTMR_START	= 0x2,
	CSV_GUEST_USER_RTMR_READ	= 0x3,
	CSV_GUEST_USER_RTMR_EXTEND	= 0x4,
};

/**
 * struct csv_guest_user_rtmr_status - RTMR_STATUS subcommand parameters
 *
 * @version: the RTMR version used in the guest. When in state
 * 	     RTMR_STATE_INIT, it will be fixed.
 * @state: the state of the guest's RTMR.
 */
struct csv_guest_user_rtmr_status {
	__u16 version;	/* Out */
	__u8  state;	/* Out */
} __attribute__((packed));

/**
 * struct csv_guest_user_rtmr_start - RTMR_START subcommand parameters
 *
 * @version: the RTMR version requested by the guest.
 */
struct csv_guest_user_rtmr_start {
	__u16 version;	/* In,Out */
} __attribute__((packed));

/**
 * struct csv_guest_user_rtmr_read - RTMR_READ subcommand parameters
 *
 * @bitmap: the bitmap specified the RTMR registers to read.
 * @data: the buffer to store RTMR registers' data returned by the firmware.
 * 	  If read more than one RTMR register, user should provide a larger
 * 	  buffer.
 */
struct csv_guest_user_rtmr_read {
	__u32 bitmap;
	__u8  data[CSV_RTMR_REG_SIZE];
} __attribute__((packed));

/**
 * struct csv_guest_user_rtmr_extend - RTMR_EXTEND subcommand parameters
 *
 * @index: the index for extending the RTMR register.
 * @rsvd: reserved, just for alignment.
 * @data_len: the length of the data to be extended.
 * @data: the data to be extended to the RTMR register.
 */
struct csv_guest_user_rtmr_extend {
	__u8  index;
	__u8  rsvd;
	__u16 data_len;
	__u8  data[CSV_RTMR_EXTEND_LEN];
} __attribute__((packed));

/**
 * struct csv_rtmr_req - RTMR request command
 *
 * @buf: the RTMR subcommand buffer.
 * @len: the length of RTMR subcommand.
 * @subcmd_id: the identifier of the RTMR subcommand.
 * @rsvd: reserved, just for alignment.
 * @fw_error_code: the return code that a RTMR subcommand returned by the
 * 		   firmware.
 */
struct csv_rtmr_req {
	__u64 buf;		/* In */
	__u64 len;		/* In,Out */
	__u16 subcmd_id;	/* In */
	__u16 rsvd;		/* Reserved */
	__u32 fw_error_code;	/* Out */
} __attribute__((packed));

/*
 * CSV_CMD_RTMR - RTMR request with user data using secure call.
 *
 * Returns 0 on success, and standard errono on other failures.
 */
#define CSV_CMD_RTMR	_IOWR('D', 2, struct csv_rtmr_req)


#define CCEL_TABLE		"/sys/firmware/acpi/tables/CCEL"
#define CCEL_SIG		"CCEL"

#define EV_NO_ACTION		0x00000003
#define EVENT_LOG_OUT_FILE	"eventlog.bin"

#define RTMR_HASH_ALG_SM3_256	0x0012

// 结构体参考：CCEL ACPI 表结构
typedef struct {
    char     Signature[4];     // "CCEL"
    uint32_t Length;
    uint8_t  Revision;
    uint8_t  Checksum;
    char     OemId[6];
    char     OemTableId[8];
    uint32_t OemRevision;
    uint32_t CreatorId;
    uint32_t CreatorRevision;
    uint32_t Version;
    uint64_t LogLen;
    uint64_t LogStart;
} __attribute__((packed)) CCEL;

typedef struct {
    uint8_t digest[20];
} __attribute__((packed)) TCG_DIGEST;

typedef struct {
    uint32_t PCRIndex;
    uint32_t EventType;
    TCG_DIGEST digest;
    uint32_t EventSize;
    uint8_t  Event[];
}__attribute__((packed)) TCG_PCR_EVENT_HDR;

// DigestValue 表示一个哈希算法的摘要
typedef struct {
    uint16_t hashAlg;
    uint8_t  digest[32];
}__attribute__((packed)) DigestValue;

// TPML_DIGEST_VALUES 结构（仅支持单个 SM3 digest）
typedef struct {
    uint32_t count;
    DigestValue digests[1]; // 简化只支持一个
} __attribute__((packed)) TPML_DIGEST_VALUES;

// TCG_PCR_EVENT2
typedef struct {
    uint32_t PCRIndex;
    uint32_t EventType;
    TPML_DIGEST_VALUES digests;
    uint32_t EventSize;
    uint8_t  Event[];
} __attribute__((packed)) TCG_PCR_EVENT2;


int handle_subcmd_rtmr(int argc, char *argv[]);

#endif  /* __CSV_RTMR_H__ */
